home *** CD-ROM | disk | FTP | other *** search
-
- ; Associative Dimensioning
-
- ; by Kelvin R. Throop
- ; Revision 3 -- May 18, 1986
-
- ; BACKGROUND
-
- ; Dimensions which change automatically when the associated geometry is
- ; modified are a very useful feature and oft requested by AutoCAD users.
- ; Autodesk will probably provide this capability in a future AutoCAD
- ; release, but until then a workable facility can be implemented in
- ; AutoLISP.
-
- ; There are two ways to provide this capability. To avoid semantic
- ; tangles, I will designate them "attached dimensions" and "stretchable
- ; dimensions". Both are ways of achieving what I will term "associative
- ; dimensioning".
-
- ; An attached dimension is an entity which is linked in the database to
- ; the point on the geometry which it specifies. This implies a pointer
- ; (associativity, in the IGES sense) from the dimension to the geometry
- ; and probably a backpointer from the geometry to the dimension. The
- ; dimension may have other non-geometric properties, such as text style,
- ; dimension line location, arrow style, etc., but its measurement is
- ; derived directly from the database.
-
- ; When any editing operation modifies the point in the database to which
- ; the dimension points, the dimension is recalculated and updated on the
- ; screen. Because the dimension is specified as a relation between
- ; database points, any editing operation which modifies a point will
- ; automatically update the dimension.
-
- ; Attached dimensions are the obvious way of allowing editing to
- ; automatically update dimensions. The implementation problems, and the
- ; problems in explaining such a system to the user, however, are
- ; daunting. For example, suppose the user draws a box and places a
- ; horizontal dimension along the top. Next, the user draws both
- ; diagonals of the box, and attaches another box to the right.
-
- ; The right end of the dimension now points to the intersection of three
- ; lines. Suppose only one is moved. Does the dimension move? Does the
- ; dimension attach to only the original top of the box? Why not the
- ; right side also? You see the problem: there is no graphical
- ; indication of which the dimension attaches, and it's far from clear
- ; that a drafter is likely to think in terms of pointers and attachment
- ; lists: he KNOWS what the bloody dimension points to, thank you!
-
- ; Stretchable dimensions are drawing entities with a set of key points
- ; which specify their value. Drawing a stretchable dimension inserts
- ; one of these entities, and draws a dimension value based on the
- ; definition points. (We will henceforth consider linear dimensions as
- ; an example; the extrapolation to other dimension types should be
- ; self-evident). In a linear dimension, the two extension line
- ; attachment points specify the distance to be dimensioned. The
- ; dimension is assumed to be one entity, so it may be moved bodily by
- ; any of the editing commands, but its internal structure is left
- ; unchanged by them. The STRETCH command, however, allows one to grow
- ; or shrink the dimension if only one of its endpoints is caught in the
- ; window being stretched. When such a STRETCH is performed, the
- ; dimension is remeasured and updated on the screen to represent the new
- ; measurement.
-
- ; Note that stretchable linear dimensions are really just very overdone
- ; line entities: when you change their endpoints, you just get a lot
- ; more action than for a mundane old line entity.
-
- ; USER NOTES
-
- ; Stretchable dimensions can be added to AutoCAD via AutoLISP. They
- ; aren't even particularly difficult to implement. This Lisp program
- ; and associated menu and drawing demonstrate stretchable linear
- ; dimensions. This is in no way a finished product. It is intended to
- ; illustrate what can be done with AutoLISP and to serve as a jumping
- ; off point for developers who wish to add such facilities to their
- ; packages.
-
- ; Be sure you download all of the related files:
-
- ; ADIM.MNU - Control menu
- ; ADIMBLK.DWG - Data block definition
- ; ADIM.LSP - Lisp implementation
-
- ; To exercise the facility, load the files into your current working
- ; drawing directory. Bring up AutoCAD on a new drawing, and enter the
- ; command:
-
- ; MENU ADIM
-
- ; This will load the associative dimensioning menu. Pick the LOAD item
- ; on the menu, and the Lisp portion of the package will be loaded.
-
- ; To insert an associative linear dimension, pick DIM on the menu (or
- ; enter the command ADIM). You will be asked:
-
- ; Dimension type (horiz/vertical/aligned):
-
- ; Enter the desired type (no abbreviations, please). Then reply to the
- ; prompts:
-
- ; First extension line location:
- ; Second extension line location:
- ; Dimension line location:
-
- ; with points specifying the dimension. Any of the dimensioning
- ; variables may be preset with the drawing modes you prefer.
-
- ; The dimension will be drawn on the screen. Go ahead and draw several
- ; dimensions, attaching them to whatever geometry you like.
-
- ; To stretch dimensions, pick STRETCH on the menu. Follow the prompts
- ; for the command (which will be defaulted to a single pick by CROSSES),
- ; and window dimension endpoints. After the geometry is updated, all
- ; the dimensions will be changed automatically.
-
- ; If you prefer to "roll your own" STRETCH command, just type DIMUPD to
- ; update the dimensions after the STRETCH command completes.
-
- ; HOW DOES IT WORK?
-
- ; When a dimension is acquired by the DIM menu pick (ADIM command), the
- ; C:ADIM Lisp function obtains the arguments, then calls DRAWDIM to
- ; construct the dimension. DRAWDIM inserts two instances of the block
- ; ADIMBLK before the dimension. This block is inserted at either end of
- ; the dimensioned distance, with attributes which record all of the
- ; user-supplied information to the command. Then AutoCAD is allowed to
- ; draw the dimension using the DIM1 command. The entities which went
- ; into the dimension are then collected into a block (given a unique
- ; name from the current time), and inserted at -3000,-3000 so the
- ; insertion point of the block will not be caught in a STRETCH window.
-
- ; After a STRETCH, C:DIMUPD is called. It obtains the selection set
- ; used by the STRETCH by (ssget "p") and scans it. If ADIMBLKs were
- ; caught in the selection set, endpoints of dimensions were changed. If
- ; this has happened, DIMUPD steps forward and deletes the dimension
- ; block, then calls DRAWDIM to update the dimension.
-
- ; PROBLEMS
-
- ; Deleting the old dimension block reference doesn't get rid of the
- ; block definition, and there's no command to do this. The user should
- ; periodically PURGE block definitions if a lot of dimensions are being
- ; changed.
-
- ; Moving both endpoints of a dimension messes it up. I was lazy and did
- ; not scan the selection set for the special case of both endpoints
- ; being moved. This code was a proof of concept, and I chose not to
- ; make it exhaustive. The fix is obvious.
-
- ; When you move the second point of a dimension, a redundant ADIMBLK P1
- ; remains in the database. AutoLISP should have an (ENTPREV) function
- ; to get the preceding entity. Lacking one, when the second definition
- ; point is picked I have the choice of leaving the first in the database
- ; or scanning the entire database to find and delete it. I chose to
- ; leave it there, since any subsequent change which catches it will
- ; delete it.
-
- ; WHY IS IT SO SLOW?
-
- ; You might be surprised. As far as I can tell, DRAWDIM and DIUMPD
- ; spend most of their time converting floating point numbers to and from
- ; ASCII. Since the only way I can save points in attributes is to store
- ; two attributes as 12 digit precision scientific notation reals, I have
- ; to go through a lot of editing and scanning, and it takes a long time.
-
- (defun C:ADIM (/ p1 p2 p3 s bm ce)
-
- ; Obtain dimension type string
-
- (setq s "")
- (while (= (strlen s) 0)
- (setq s (getstring "\nDimension type (horiz/vertical/aligned): "))
- (setq s (strcase s))
- (if (not (or (= s "HORIZ") (= s "VERTICAL") (= s "ALIGNED")))
- (setq s "")
- )
- )
-
- ; Get dimension definition points
-
- (setq p1 (getpoint "\nFirst extension line location: "))
- (setq p2 (getpoint "\nSecond extension line location: " p1))
-
- ; Obtain extension line location
-
- (setq p3 (getpoint "\nDimension line location: "))
-
- (setq bm (getvar "blipmode"))
- (setq ce (getvar "cmdecho"))
- (setvar "blipmode" 0)
- (setvar "cmdecho" 0)
-
- (drawdim s p1 p2 p3)
-
- (setvar "blipmode" bm)
- (setvar "cmdecho" ce)
- )
-
- ; Draw dimension and insert attribute blocks
-
- (defun drawdim (s p1 p2 p3 / e1 s1 bn)
-
- ; Insert attribute blocks at both dimensioned points
-
- (command "insert" "adimblk" p1 1 1 0)
- (command "P1") ; Dimval
- (command (rtos (car p1) 1 12)) ; p1x
- (command (rtos (cadr p1) 1 12)) ; p1y
- (command (rtos (car p2) 1 12)) ; p2x
- (command (rtos (cadr p2) 1 12)) ; p2y
- (command (rtos (car p3) 1 12)) ; p3x
- (command (rtos (cadr p3) 1 12)) ; p3y
- (command s) ; type
-
- (command "insert" "adimblk" p2 1 1 0)
- (command "P2") ; Dimval
- (command (rtos (car p1) 1 12)) ; p1x
- (command (rtos (cadr p1) 1 12)) ; p1y
- (command (rtos (car p2) 1 12)) ; p2x
- (command (rtos (cadr p2) 1 12)) ; p2y
- (command (rtos (car p3) 1 12)) ; p3x
- (command (rtos (cadr p3) 1 12)) ; p3y
- (command s) ; type
-
- ; Draw the dimension
-
- (setq e1 (entlast)) ; Remember last entity in database
- (command "dim1" s p1 p2 p3 "")
-
- ; Now suck up the entities generated by dimensioning and make
- ; a block of them.
-
- (setq s1 (ssadd)) ; Create selection set of entities
- (while (setq e1 (entnext e1))
- (ssadd e1 s1)
- )
- ; Make unique name for block from current date and time
- (setq s (rtos (getvar "date") 2 9))
- (setq bn (strcat "$DIM" (substr s 1 7) (substr s 9)))
- (command "block" bn '(-3000 -3000) s1 "")
- (command "insert" bn '(-3000 -3000) 1 1 0)
- )
-
- ; Postprocessing for stretch command which updates dimensions
-
- (defun C:DIMUPD (/ s1 bm ce hen)
-
- (setq bm (getvar "blipmode"))
- (setq ce (getvar "cmdecho"))
- (setvar "blipmode" 0)
- (setvar "cmdecho" 0)
-
- (setq s1 (ssget "p")) ; Obtain last selection set
- (setq i 0)
- (while (setq en (ssname s1 i))
- (setq e (entget en))
- (if (and (= (cdr (assoc 0 e)) "INSERT")
- (= (cdr (assoc 2 e)) "ADIMBLK")
- )
- (progn
- (setq hen en)
- (setq ndp (cdr (assoc 10 e))) ; New dimensioned point
- (setq al (basl))
- (entdel hen) ; Delete dimension record info
- (setq ok t)
- (if (= (setq dv (cdr (assoc "DIMVAL" al))) "P1")
- (progn
- ; See if this P1 is followed by a P2. If so,
- ; delete it also.
- (setq e (entget (setq en (entnext en))))
- (if (and (= (cdr (assoc 0 e)) "INSERT")
- (= (cdr (assoc 2 e)) "ADIMBLK")
- )
- (progn
- (setq hen en)
- (setq al1 (basl))
- (if (not (= (cdr (assoc "DIMVAL" al1)) "P2"))
- (setq ok nil) ; Nope. Don't blunder on
- (entdel hen) ; Valid. Delete old P2
- )
- )
- (setq ok nil)
- )
- )
- )
- (setq e (entget (setq en (entnext en))))
- (if (and ok (= (cdr (assoc 0 e)) "INSERT")
- (= (substr (cdr (assoc 2 e)) 1 4) "$DIM"))
- (progn
- (entdel en)
- (setq p1 (list (cdr (assoc "DIMP1X" al))
- (cdr (assoc "DIMP1Y" al))))
- (setq p2 (list (cdr (assoc "DIMP2X" al))
- (cdr (assoc "DIMP2Y" al))))
- (setq p3 (list (cdr (assoc "DIMP3X" al))
- (cdr (assoc "DIMP3Y" al))))
- (if (= dv "P1")
- (setq p1 ndp)
- (setq p2 ndp)
- )
- (drawdim (cdr (assoc "DIMTYPE" al)) p1 p2 p3)
- )
- )
- )
- )
- (setq i (1+ i))
- )
-
- (setvar "blipmode" bm)
- (setvar "cmdecho" ce)
- )
-
- ; Build association list from attributes
-
- (defun basl (/ v e t o)
- (setq v nil)
- (while (not (= (cdr (assoc 0 (setq e (entget (setq en (entnext en))))))
- "SEQEND"))
- (setq t (cdr (assoc 2 e)))
- (setq o (cdr (assoc 1 e)))
- (if (= (substr t 1 4) "DIMP")
- (setq o (atof o))
- )
- (setq v (cons (cons t o) v))
- )
- v
- )
-